package com.demo.alg.chapter15动态规划.背包问题;

/**https://www.cnblogs.com/lfeng1205/p/5981198.html
 * 在N件物品取出若干件放在容量为W的背包里，每件物品的体积为W1，W2……Wn（Wi为整数），与之相对应的价值为P1,P2……Pn（Pi为整数）。求背包能够容纳的最大价值。
 *
 * 先将原始问题一般化，欲求背包能够获得的总价值，即欲求前i个物体放入容量为m（kg）背包的最大价值c[i][m]——使用一个数组来存储最大价值，当m取10，i取3时，即原始问题了。而前i个物体放入容量为m（kg）的背包，又可以转化成前(i-1)个物体放入背包的问题。下面使用数学表达式描述它们两者之间的具体关系。

　　表达式中各个符号的具体含义。

　　w[i] :  第i个物体的重量；

　　p[i] : 第i个物体的价值；

　　c[i][m] ： 前i个物体放入容量为m的背包的最大价值；

　　c[i-1][m] ： 前i-1个物体放入容量为m的背包的最大价值；

　　c[i-1][m-w[i]] ： 前i-1个物体放入容量为m-w[i]的背包的最大价值；

	由此可得：c[i][m]=max{c[i-1][m-w[i]]+pi , c[i-1][m]}，更具体的解释：
	不放入第i个物品，即c[i][m]=c[i-1][m]
	放入第i个物品，即c[i][m]=c[i-1][m-w[i]]+p[i]
 *
 */
public class Dp05 {

	public static void main(String[] args) {
        int m = 8;
        int n = 4;
        int w[] = new int[]{2, 3, 4, 5};
        int p[] = new int[]{3, 4, 5, 6};
        int c[][] = BackPack_Solution(m, n, w, p);
        for (int i = 1; i <=n; i++) {
            for (int j = 1; j <=m; j++) {
                System.out.print(c[i][j] + "\t");
                if(j == m){
                    System.out.println();
                }
            }
        }
    }

	/**
     * @param m 表示背包的最大容量
     * @param n 表示商品个数
     * @param w 表示商品重量数组
     * @param p 表示商品价值数组
     */
    public static int[][] BackPack_Solution(int m, int n, int[] w, int[] p) {
        //c[i][v]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值
        int c[][] = new int[n + 1][m + 1];

        for (int i = 1; i < n + 1; i++) {
            for (int j = 1; j < m + 1; j++) {
                //当物品为i件重量为j时，如果第i件的重量(w[i-1])小于重量j时，c[i][j]为下列两种情况之一：
                //(1)物品i不放入背包中，所以c[i][j]为c[i-1][j]的值
                //(2)物品i放入背包中，则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值
                if (w[i - 1] <= j)
                    c[i][j] = Math.max(c[i - 1][j], c[i - 1][j - w[i - 1]] + p[i - 1]);
                else
                    c[i][j] = c[i - 1][j];
            }
        }
        return c;
    }

}
